/**
 * @file xos.c
 * @author eric
 * @brief
 * @version 0.1
 * @date 2024-09-18
 *
 * @copyright Copyright (c) 2024
 *
 */

#include "xos.h"
#include <stdio.h>

// 判断，时间是否超时
#define TIME_AFTER(a, b) ((a) >= (b))

typedef struct task_node list_node_t;

static uint8_t          is_init;   // 判断是否已经初始化??
static struct list_head head;      // 任务链表头
static task_cb          sleep_handle = NULL;

static uint8_t    idel_cnt = 0;
volatile uint32_t jiffies  = 0;

/************************************************************************
 * task
 ************************************************************************/
static int xos_task_is_exists(task_t* task)
{
    int          ret  = FALSE;
    list_node_t* node = NULL;

    if (is_init == FALSE) {
        return ret;
    }

    list_for_each_entry(node, &head, list, task_t)
    {
        if (node == task) {
            ret = TRUE;
            break;
        }
    }

    return ret;
}

int xos_task_add(task_t* task)
{
    // 初始化链表头
    if (is_init == FALSE) {
        INIT_LIST_HEAD(&head);
        is_init = TRUE;
    }

    if (task == NULL) {
        return FALSE;
    }

    // 已经存在，不能添加
    if (xos_task_is_exists(task) != FALSE) {
        return FALSE;
    }

    ENTER_CRITICAL();

    task->is_start = TRUE;
    task->is_run   = TRUE;
    task->event    = 0;

    list_add(&(task->list), &head);

    EXIT_CRITICAL();

    return TRUE;
}

int xos_task_delete(task_t* task)
{
    int          ret  = FALSE;
    list_node_t* node = NULL;
    list_node_t* n    = NULL;

    if (is_init == FALSE) {
        return ret;
    }

    ENTER_CRITICAL();

    list_for_each_entry_safe(node, n, &head, list, task_t)
    {
        if (node == task) {
            list_del(&node->list);
            ret = TRUE;
            break;
        }
    }

    EXIT_CRITICAL();

    return ret;
}

void xos_task_loop(void)
{
    uint8_t      is_timeout = FALSE;
    uint8_t      is_once    = FALSE;
    uint8_t      is_timer   = FALSE;
    uint8_t      is_busy    = FALSE;
    uint32_t     events     = 0;
    list_node_t* node       = NULL;

    if (is_init == FALSE) {
        return;
    }

    list_for_each_entry(node, &head, list, task_t)
    {
        is_timer   = ((TASK_ONCE == node->mode) || (TASK_REPEAT == node->mode));
        is_once    = (TASK_ONCE == node->mode);
        is_timeout = TIME_AFTER(jiffies, node->tick);

        // 判断，定时任务，运行时间是否已到？？
        if (is_timer)   // 定时任务
        {
            if ((node->is_start != FALSE) && is_timeout)   // 定时时间到
            {
                ENTER_CRITICAL();
                node->is_run = TRUE;
                node->tick   = jiffies + node->period;   // 更新当前任务tick
                EXIT_CRITICAL();
            } else {
                node->is_run = FALSE;
            }
        }

        // 如果允许运行
        if (node->is_run) {
            // 执行任务函数
            if (NULL != node->func) {
                // 事件重置
                events = node->event;
                if (events) {
                    ENTER_CRITICAL();
                    node->event = 0;
                    EXIT_CRITICAL();
                }

                node->func(node->arg, events);
            }

            is_busy |= node->is_busy;

            // 定时任务，运行一次后，等待触发
            if (is_timer) {
                ENTER_CRITICAL();
                node->is_run = FALSE;
                EXIT_CRITICAL();

                // 如果是单次任务，执行完此次任务后，停止触发
                if (is_once) {
                    node->is_start = FALSE;
                }
            }
        }
    }

    // 忙碌操作
    if (!is_busy) {
        if (++idel_cnt > 2) {
            idel_cnt = 0;
            if (sleep_handle) {
                sleep_handle(0, is_busy);
            }
        }
    } else {
        idel_cnt = 0;
    }
}

int xos_task_start(task_t* task)
{
    if (task == NULL) {
        return FALSE;
    }

    ENTER_CRITICAL();

    // 普通任务直接运行，定时任务只触发start
    if (task->mode == TASK_LOOP) {
        task->is_start = TRUE;
        task->is_run   = TRUE;
    } else {
        task->tick     = jiffies + task->period;   // 更新定时周期
        task->is_start = TRUE;
        task->is_run   = FALSE;
    }

    EXIT_CRITICAL();

    return TRUE;
}

int xos_task_stop(task_t* task)
{

    if (task == NULL) {
        return FALSE;
    }

    ENTER_CRITICAL();

    task->is_start = FALSE;
    task->is_run   = FALSE;

    EXIT_CRITICAL();

    return TRUE;
}

void xos_timer_ticker(void)
{
    jiffies++;
}

/************************************************************************
 * event
 ************************************************************************/
int xos_event_set(task_t* task, uint32_t event)
{
    int ret = FALSE;

    ENTER_CRITICAL();

    if (xos_task_is_exists(task) == TRUE) {
        task->event |= event;
        ret = TRUE;
    }

    EXIT_CRITICAL();

    return ret;
}

int xos_event_reset(task_t* task, uint32_t event)
{
    int ret = FALSE;

    ENTER_CRITICAL();

    if (xos_task_is_exists(task) == TRUE) {
        task->event &= ~(event);
        ret = TRUE;
    }

    EXIT_CRITICAL();

    return ret;
}
/************************************************************************
 * other
 ************************************************************************/
void xos_delay_ms(uint32_t ms)
{
    uint32_t is_start = jiffies;
    while ((jiffies - is_start) <= ms);
}

int xos_set_sleep_handel(task_cb func)
{
    sleep_handle = func;
    return 0;
}
